
/*
 *  Copyright t lefering, David Given
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  These are the four essential freedoms with GNU GPL software:
 *  1: freedom to run the program, for any purpose
 *  2: freedom to study how the program works, and change it to make it do what you wish
 *  3: freedom to redistribute copies to help your Free Software friends
 *  4: freedom to distribute copies of your modified versions to your Free Software friends
 *   ,           ,
 *  /             \
 * ((__-^^-,-^^-__))
 * `-_---'  `---_-'
 *  `--|o`   'o|--'
 *      \  `  /
 *       ): :(
 *       :o_o:
 *        "-"
 */

#include "globals.h"

static avltree_t binfostore = NULL;
static struct binfo **binfolist = NULL;
static int binfocount = 0;
static int iterator = 0;

static int compare_cb(const void *lhs, const void *rhs)
{
	const struct binfo *n1 = lhs;
	const struct binfo *n2 = rhs;
	unsigned int i1 = (unsigned int)(size_t)n1->bb;
	unsigned int i2 = (unsigned int)(size_t)n2->bb;
	if (i1 < i2)
		return -1;
	else if (i1 > i2)
		return 1;
	return 0;
}

struct binfo *lookup_binfo_of_basic_block(struct basic_block *bb)
{
	struct binfo key;
	key.bb = bb;

	struct binfo *data = avl_search(binfostore, compare_cb, &key, 0);
	if (!data) {
		data = calloc(1, sizeof(struct binfo));
		data->bb = bb;
		avl_insert(&binfostore, compare_cb, data, NULL);
	}

	return data;
}

void reset_binfo(void)
{
	binfostore = NULL;
	binfolist = NULL;
}

static void enumerate_cb(void *node)
{
if(node){}
	binfocount++;
}

static void iterate_cb(void *node)
{
	binfolist[iterator] = node;
	iterator++;
}

static int sortindex_cb(const void *p1, const void *p2)
{
	struct binfo *const *o1 = p1;
	struct binfo *const *o2 = p2;
	int id1 = (*o1)->id;
	int id2 = (*o2)->id;

	if (id1 < id2)
		return -1;
	else if (id1 > id2)
		return 1;
	return 0;
}

void get_binfo_list(struct binfo ***list, int *count)
{
	if (!binfolist) {
		binfocount = 0;
		avl_traverse(binfostore, enumerate_cb);

		binfolist = calloc(1, (sizeof(struct binfo *) * binfocount));
		iterator = 0;
		avl_traverse(binfostore, iterate_cb);

		qsort(binfolist, binfocount, sizeof(struct binfo *), sortindex_cb);
	}

	*list = binfolist;
	*count = binfocount;
	return;
}

/* end */
